﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XQ.Extension.EmitMapper;
using XQ.Extension.EmitMapper.MappingConfiguration;

namespace XQ.Extension
{
    public static class MapExtesion
    {
        //
        // 摘要:
        //     使用单例节省存储空间，这个对象进行了缓存. 并不是线程安全的。
        private static readonly DefaultMapConfig _defaultMapConfig;

        private static readonly Func<string, string, bool> CompareFun;

        static MapExtesion()
        {
            CompareFun = (string source, string dest) => source != null && dest != null && source.ToUpper() == dest.ToUpper();
            _defaultMapConfig = new MyMapConfig().ShallowMap().MatchMembers(CompareFun).NullSubstitution<decimal?, decimal>((object value) => 0m)
                .NullSubstitution<int?, int>((object value) => 0)
                .NullSubstitution<bool?, bool>((object v) => false)
                .NullSubstitution<short?, short>((object v) => 0)
                .NullSubstitution<long?, long>((object v) => 0L);
        }

        public static IEnumerable<T> MapTo<W, T>(this IEnumerable<W> entity, Action<W, T> action = null) where W : class where T : class, new()
        {
            return MapList(entity, action);
        }

        public static T MapTo<W, T>(this W entity, Action<W, T> action = null) where W : class where T : class, new()
        {
            T val = MapEntity<W, T>(entity);
            action?.Invoke(entity, val);
            return val;
        }

        internal static IEnumerable<T> MapList<W, T>(IEnumerable<W> entitys, Action<W, T> action = null) where W : class where T : class, new()
        {
            if (entitys == null)
            {
                yield break;
            }

            foreach (W entity in entitys)
            {
                T val = MapEntity<W, T>(entity);
                action?.Invoke(entity, val);
                yield return val;
            }
        }

        public static T MapEntity<W, T>(W entity) where W : class where T : class, new()
        {
            return ObjectMapperManager.DefaultInstance.GetMapper<W, T>(_defaultMapConfig).Map(entity, new T());
        }

        public static T Merge<W, T>(this T oldEntity, W entity) where W : class where T : class, new()
        {
            return ObjectMapperManager.DefaultInstance.GetMapper<W, T>(_defaultMapConfig).Map(entity, oldEntity);
        }
    }
}
